package com.ahaoyou.service;

import cn.hutool.core.collection.CollectionUtil;
import com.ahaoyou.entity.Subject;
import com.ahaoyou.entity.User;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * @Author LH
 * @create 2021/12/22 18:19
 */
@Service
@Slf4j
public class EsService {

    @Autowired
    private RestHighLevelClient client;

    //id相同可以用作修改  id相同会覆盖
    public void saveUsers(List<User> users) {
        if (CollectionUtil.isEmpty(users)) {
            throw new RuntimeException("数据为空");
        }
        try {
            //批量执行api
            BulkRequest bulkRequest = new BulkRequest();
            users.forEach((v) -> {
                IndexRequest request = new IndexRequest("user_index");
                JSONObject user = (JSONObject) JSONObject.toJSON(v);
                request.id(user.getString("userId"));
                request.source(user.toJSONString(), XContentType.JSON);
                bulkRequest.add(request);
            });
            BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT);
            log.info("批量保存user_index索引响应状态:{}", response.status());
            log.info("批量保存user_index索引结果:{}", response.buildFailureMessage());
        } catch (IOException e) {
            e.printStackTrace();
            log.warn("添加user_index索引数据失败,错误信息:{}", e.getMessage());
        }
    }

    public void saveSubjects(List<Subject> subjects) {
        if (CollectionUtil.isEmpty(subjects)) {
            throw new RuntimeException("数据为空");
        }
        try {
            BulkRequest bulkRequest = new BulkRequest();
            subjects.forEach((v) -> {
                IndexRequest request = new IndexRequest("subject");
                JSONObject subject = (JSONObject) JSONObject.toJSON(v);
                request.id(subject.getString("id"));
                request.source(subject.toJSONString(), XContentType.JSON);
                bulkRequest.add(request);
            });
            BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT);
            log.info("批量保存subject索引结果:{}", response.buildFailureMessage());
        } catch (IOException e) {
            e.printStackTrace();
            log.warn("添加subject索引数据失败,错误信息:{}", e.getMessage());
        }
    }

    /**
     * 根据查询条件删除
     */
    public void deleteByQuery() {
        try {
            DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest("user_index");
            //查询条件
            deleteByQueryRequest.setQuery(QueryBuilders.termQuery("password", "123456"));
            //设置分多少批次完成  默认100
            deleteByQueryRequest.setBatchSize(1);
            BulkByScrollResponse bulkByScrollResponse = client.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);
            log.warn("删除结果:{}", bulkByScrollResponse.getStatus());
        } catch (IOException e) {
            e.printStackTrace();
            log.error("删除时出现异常");
        }
    }

    /**
     * 查询全部
     */
    public void selectAll() throws IOException {
        SearchRequest searchRequest = new SearchRequest("subject");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        sourceBuilder.size(2);
        searchRequest.source(sourceBuilder);
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
        Arrays.stream(search.getHits().getHits()).forEach((k) -> {
            JSONObject json = JSONObject.parseObject(k.getSourceAsString());
            System.out.println(json);
        });
    }

    public void testBoolQuery() throws IOException {
        SearchRequest request = new SearchRequest("subject");
        // 查询条件构造
        SearchSourceBuilder builder = new SearchSourceBuilder();
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        // 这里查询含义id大于等于2并且value不能等于红色,如果id>3的话那么它的相似度更高。
        queryBuilder.must(QueryBuilders.rangeQuery("id").gte("2"));
        queryBuilder.mustNot(QueryBuilders.matchQuery("value", "红色"));
        queryBuilder.should(QueryBuilders.rangeQuery("id").gt("3"));
        builder.query(queryBuilder);
        request.source(builder);
        SearchResponse responses = client.search(request, RequestOptions.DEFAULT);
        Arrays.stream(responses.getHits().getHits()).forEach((k) -> {
            JSONObject json = JSONObject.parseObject(k.getSourceAsString());
            System.out.println(json);
        });
    }

    /**
     * 分页查询
     */
    public void testPageQuery() throws IOException {
        SearchRequest request = new SearchRequest("subject");
        // 查询条件构
        SearchSourceBuilder builder = new SearchSourceBuilder();
        MatchAllQueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
        // query <==> select
        builder.query(queryBuilder);
        // 分页查询
        builder.from(0);
        builder.size(2);
        // 指定排序
        builder.sort("id", SortOrder.ASC);
        request.source(builder);
        SearchResponse responses = client.search(request, RequestOptions.DEFAULT);
        Arrays.stream(responses.getHits().getHits()).forEach((k) -> {
            JSONObject json = JSONObject.parseObject(k.getSourceAsString());
            System.out.println(json);
        });
    }

    /**
     * 高亮查询
     */
    public void testHighLightQuery() throws IOException {
        SearchRequest request = new SearchRequest("subject");

        // 查询条件构
        SearchSourceBuilder builder = new SearchSourceBuilder();
        // 注意高亮全部查询时无意义
        MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("key", "subject");
        builder.query(queryBuilder);

        // 高亮查询，和查询同级
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");
        highlightBuilder.field("key");

        builder.highlighter(highlightBuilder);
        request.source(builder);
        SearchResponse responses = client.search(request, RequestOptions.DEFAULT);
        for (SearchHit searchHit : responses.getHits()) {
            System.out.println(searchHit.getHighlightFields());
            System.out.println(searchHit.getHighlightFields().keySet());
            System.out.println(searchHit.getHighlightFields().get("key"));
        }
    }
}